package com.gzc.just.play.last.war.common.scanner;

import com.google.protobuf.MessageLite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.gzc.just.play.last.war.common.annotation.MessageDeserializers;
import com.gzc.just.play.last.war.common.serializer.AutoMessageDeserializerFactory;
import com.gzc.just.play.last.war.common.serializer.GenericProtobufDeserializer;
import jakarta.annotation.PostConstruct;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 消息反序列化器扫描器
 * 
 * 支持两种注册方式：
 * 1. 传统方式：扫描实现了MessageDeserializer接口的类
 * 2. 声明式方式：扫描带有@MessageDeserializer注解的配置类，自动创建GenericProtobufDeserializer
 * 
 * 声明式方式的优点：
 * - 无需为每个消息类型创建单独的类
 * - 集中配置，易于管理
 * - 自动支持压缩/加密等选项
 */
@Component
public class MessageDeserializerScanner {
    private static final Logger logger = LoggerFactory.getLogger(MessageDeserializerScanner.class);
    
    @Autowired
    private ApplicationContext applicationContext;
    
    /**
     * 按模块名称分组的反序列化器
     */
    private Map<String, Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>>> deserializersByModule = new HashMap<>();
    
    /**
     * 全局反序列化器映射
     */
    private Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>> globalDeserializers = new HashMap<>();
    
    @PostConstruct
    public void scanAndRegister() {
        logger.info("Starting message deserializer scanning...");
        
        int traditionalCount = 0;
        int declarativeCount = 0;
        
        // 方式1：扫描实现了MessageDeserializer接口的Bean（传统方式）
        Collection<com.gzc.just.play.last.war.common.serializer.MessageDeserializer> deserializers = 
            applicationContext.getBeansOfType(com.gzc.just.play.last.war.common.serializer.MessageDeserializer.class).values();
        
        for (com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?> deserializer : deserializers) {
            com.gzc.just.play.last.war.common.annotation.MessageDeserializer annotation = 
                deserializer.getClass().getAnnotation(com.gzc.just.play.last.war.common.annotation.MessageDeserializer.class);
            if (annotation != null) {
                registerDeserializer(deserializer, annotation);
                traditionalCount++;
            }
        }
        
        // 方式2：扫描带有@MessageDeserializer/@MessageDeserializers注解的配置类（声明式方式）
        // 这些类不需要实现MessageDeserializer接口
        Map<String, Object> allBeans = applicationContext.getBeansOfType(Object.class);
        for (Object bean : allBeans.values()) {
            Class<?> beanClass = bean.getClass();
            
            // 跳过已经是MessageDeserializer实现的类（已在方式1处理）
            if (bean instanceof com.gzc.just.play.last.war.common.serializer.MessageDeserializer) {
                continue;
            }
            
            // 检查是否有@MessageDeserializers（多个注解）
            MessageDeserializers multiAnnotation = beanClass.getAnnotation(MessageDeserializers.class);
            if (multiAnnotation != null) {
                for (com.gzc.just.play.last.war.common.annotation.MessageDeserializer annotation : multiAnnotation.value()) {
                    createAndRegisterGenericDeserializer(annotation);
                    declarativeCount++;
                }
            }
            
            // 检查是否有单个@MessageDeserializer
            com.gzc.just.play.last.war.common.annotation.MessageDeserializer singleAnnotation = 
                beanClass.getAnnotation(com.gzc.just.play.last.war.common.annotation.MessageDeserializer.class);
            if (singleAnnotation != null && multiAnnotation == null) {
                createAndRegisterGenericDeserializer(singleAnnotation);
                declarativeCount++;
            }
        }
        
        logger.info("Completed message deserializer scanning. Traditional: {}, Declarative: {}, Total: {}", 
                   traditionalCount, declarativeCount, globalDeserializers.size());
        
        AutoMessageDeserializerFactory.registerScanner(this);
    }
    
    /**
     * 从注解创建并注册GenericProtobufDeserializer
     */
    @SuppressWarnings("unchecked")
    private void createAndRegisterGenericDeserializer(com.gzc.just.play.last.war.common.annotation.MessageDeserializer annotation) {
        int messageId = annotation.messageId();
        Class<?> messageType = annotation.messageType();
        String module = annotation.module();
        String name = annotation.name().isEmpty() ? messageType.getSimpleName() + "Deserializer" : annotation.name();
        
        // 检查消息类型是否是Protobuf消息
        if (!MessageLite.class.isAssignableFrom(messageType)) {
            logger.warn("Message type {} is not a Protobuf message, skipping declarative deserializer for messageId: {}", 
                       messageType.getName(), messageId);
            return;
        }
        
        // 创建配置选项
        GenericProtobufDeserializer.DeserializeOptions options = GenericProtobufDeserializer.DeserializeOptions.defaults();
        if (annotation.compression()) {
            options.withCompression(annotation.compressionType());
        }
        if (annotation.encryption()) {
            options.withEncryption(annotation.encryptionType(), null); // 密钥需要从配置获取
        }
        
        // 创建通用反序列化器
        GenericProtobufDeserializer<?> deserializer = new GenericProtobufDeserializer<>(
            (Class<? extends MessageLite>) messageType,
            messageId,
            module,
            options
        );
        
        // 注册
        registerDeserializerInternal(deserializer, messageId, module, name);
        
        logger.debug("Created declarative deserializer: {} for messageId: {} (type: {})", 
                    name, messageId, messageType.getSimpleName());
    }
    
    /**
     * 注册反序列化器（传统方式）
     */
    private void registerDeserializer(com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?> deserializer, 
                                com.gzc.just.play.last.war.common.annotation.MessageDeserializer annotation) {
        int messageId = annotation.messageId();
        String module = annotation.module();
        String name = annotation.name().isEmpty() ? deserializer.getClass().getSimpleName() : annotation.name();
        
        registerDeserializerInternal(deserializer, messageId, module, name);
    }
    
    /**
     * 内部注册方法
     */
    private void registerDeserializerInternal(com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?> deserializer,
                                              int messageId, String module, String name) {
        // 注册到全局映射
        com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?> existing = globalDeserializers.get(messageId);
        if (existing != null) {
            logger.warn("Overriding deserializer for messageId {}: {} -> {}", 
                       messageId, existing.getClass().getSimpleName(), name);
        }
        globalDeserializers.put(messageId, deserializer);
        
        // 注册到模块映射
        if (!module.isEmpty()) {
            Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>> moduleDeserializers = 
                deserializersByModule.computeIfAbsent(module, k -> new HashMap<>());
            
            com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?> existingModule = moduleDeserializers.get(messageId);
            if (existingModule != null) {
                logger.warn("Overriding deserializer for messageId {} in module {}: {} -> {}", 
                           messageId, module, existingModule.getClass().getSimpleName(), name);
            }
            moduleDeserializers.put(messageId, deserializer);
            
            logger.debug("Registered deserializer: {} for messageId: {} in module: {}", 
                        name, messageId, module);
        } else {
            logger.debug("Registered global deserializer: {} for messageId: {}", name, messageId);
        }
    }
    
    /**
     * 获取全局反序列化器
     */
    @SuppressWarnings("unchecked")
    public <T> com.gzc.just.play.last.war.common.serializer.MessageDeserializer<T> getDeserializer(int messageId) {
        return (com.gzc.just.play.last.war.common.serializer.MessageDeserializer<T>) globalDeserializers.get(messageId);
    }
    
    /**
     * 获取指定模块的反序列化器
     */
    @SuppressWarnings("unchecked")
    public <T> com.gzc.just.play.last.war.common.serializer.MessageDeserializer<T> getDeserializer(int messageId, String module) {
        Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>> moduleDeserializers = 
            deserializersByModule.get(module);
        if (moduleDeserializers != null) {
            return (com.gzc.just.play.last.war.common.serializer.MessageDeserializer<T>) moduleDeserializers.get(messageId);
        }
        return null;
    }
    
    /**
     * 获取所有全局反序列化器
     */
    public Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>> getAllDeserializers() {
        return new HashMap<>(globalDeserializers);
    }
    
    /**
     * 获取指定模块的所有反序列化器
     */
    public Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>> getDeserializersForModule(String module) {
        Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>> moduleDeserializers = 
            deserializersByModule.get(module);
        if (moduleDeserializers != null) {
            return new HashMap<>(moduleDeserializers);
        }
        return new HashMap<>();
    }
    
    /**
     * 获取所有模块的反序列化器
     */
    public Map<String, Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>>> getAllDeserializersByModule() {
        Map<String, Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>>> result = new HashMap<>();
        for (Map.Entry<String, Map<Integer, com.gzc.just.play.last.war.common.serializer.MessageDeserializer<?>>> entry : deserializersByModule.entrySet()) {
            result.put(entry.getKey(), new HashMap<>(entry.getValue()));
        }
        return result;
    }
}
